package com.jj.entity;

import com.jj.battle.protocol.GameProto;
import com.jj.core.utils.Hex;
import lombok.extern.slf4j.Slf4j;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

@Slf4j
public class RecorderManager {
    public static int MAX_FRAME = 100*60*60;
    List<List<PlayerOperation>> recorders = new LinkedList<>();
    int currentFrameNum = -1;

    public int getNextFrameNum(){
        return currentFrameNum + 1;
    }

    /**
     *
     * @return -1 if not frames
     */
    public int getCurrentFrameNum(){
        return currentFrameNum;
    }

    public void add(int frameNum, PlayerOperation playerOperation){
        //fill frames
        while(recorders.size() - 1 < frameNum){
            recorders.add(new LinkedList<>());
        }

        List<PlayerOperation> po = recorders.get(frameNum);
        if(po == null){
            po = new LinkedList<>();
            recorders.add(po);
        }else{
            //不删除旧操作，简单追加
//            Iterator<PlayerOperation> it =  po.iterator();
//            while(it.hasNext()){
//                PlayerOperation o = it.next();
//                if(o.getPlayerID() == playerOperation.getPlayerID()){
//                    it.remove();
//                    log.warn("remove duplicate operation:{}, using {}", o, playerOperation);
//                }
//            }
        }
        po.add(playerOperation);
    }

    public GameProto.PKG_FRAME getFrame(int frameNum){
        List<PlayerOperation> opList = recorders.get(frameNum);
        if(opList == null || opList.size() == 0){
            return GameProto.PKG_FRAME.newBuilder().setFrameNo(frameNum).build();
        }else{
            GameProto.PKG_FRAME.Builder frameBuilder = GameProto.PKG_FRAME.newBuilder();
            frameBuilder.addAllOperations(new LinkedList<>());
            frameBuilder.setFrameNo(frameNum);
            GameProto.PKG_FRAME frame = frameBuilder.build();
            return PlayerOperation.add2Frame(frameBuilder, opList);
        }
    }

    public List<GameProto.PKG_FRAME> getSynState(int beginFrameNum){
        List<GameProto.PKG_FRAME> frames = new LinkedList<>();
        for(int i = beginFrameNum; i < recorders.size(); i++){
            GameProto.PKG_FRAME frame = getFrame(i);
            frames.add(frame);
        }
        return frames;
    }

    public void addCmd(Long uid, GameProto.PKG_OPERATION cmd){
        //int frameNum = recorders.size() + 4;
        //暂时不延时4帧
        int reqFrameNum = cmd.getSendFrameNo();
        int frameNum = recorders.size();
        int insertFrameNum = 0;
        if(reqFrameNum + 4 < frameNum){
            insertFrameNum = frameNum;
        }else{
            insertFrameNum = reqFrameNum + 4;
        }

        PlayerOperation playerOperation = PlayerOperation.fromMsg(cmd, uid);
        log.debug("add cmd {} at frame {}", playerOperation, frameNum);
        add(insertFrameNum, playerOperation);
    }

    public void increaseFrame(){
        log.debug("increase frameNum {} -> {}", currentFrameNum, currentFrameNum+1);
        currentFrameNum ++;
        while(currentFrameNum > recorders.size()-1) {
            recorders.add(new LinkedList<>());
            log.debug("add new frame slot and current frame at {}", currentFrameNum);
        }
    }


    public static void main(String[] args) {


        RecorderManager recorderManager = new RecorderManager();
        for(int i = 0; i < 10; i++){
            PlayerOperation playerOperation = new PlayerOperation();
            playerOperation.setPlayerID(10001L);
            playerOperation.setKey(999);
            playerOperation.setChargeFrames(i);
            playerOperation.setMaxChargeFrame(i);
            playerOperation.setType(2);
            playerOperation.setDirection(-1);
            playerOperation.setEventID(77);
            recorderManager.add(i+5, playerOperation);

            PlayerOperation playerOperation2 = new PlayerOperation();
            playerOperation2.setPlayerID(10002L);
            playerOperation2.setKey(777);
            playerOperation2.setChargeFrames(i);
            playerOperation2.setMaxChargeFrame(i);
            playerOperation2.setType(2);
            playerOperation2.setDirection(-1);
            playerOperation2.setEventID(77);
            recorderManager.add(i, playerOperation2);
        }
        log.debug("{}", recorderManager.recorders);
        log.debug("size:{}", recorderManager.getCurrentFrameNum());
        GameProto.PKG_FRAME frame = recorderManager.getFrame(5);
        for(GameProto.DT_FRAME_CONTENT content : frame.getOperationsList()){
            PlayerOperation op  = PlayerOperation.fromMsg(content.getOperation(), content.getPlayerId());
            log.debug("op:{}", op);
        }
        log.debug("frame:\n{}", Hex.printhex2Buf(frame.toByteArray()));
    }
}
